package com.leha.mp.core.services.imp;

import com.leha.mp.core.config.WxMpConfig;
import com.leha.mp.core.dao.MpUserMapper;
import com.leha.mp.core.entity.mybatis.MpUser;
import com.leha.mp.core.entity.mybatis.MpUserExample;
import com.leha.mp.core.handler.*;
import com.leha.mp.core.services.WxMPServices;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.http.apache.DefaultApacheHttpClientBuilder;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import me.chanjar.weixin.mp.constant.WxMpEventConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class WxMPServicesImpl implements WxMPServices, InitializingBean {
    @Autowired
    private WxMpService wxMpService;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    protected LogHandler logHandler;

    @Autowired
    protected NullHandler nullHandler;

    @Autowired
    protected KfSessionHandler kfSessionHandler;

    @Autowired
    protected StoreCheckNotifyHandler storeCheckNotifyHandler;

    @Autowired
    private LocationHandler locationHandler;

    @Autowired
    private MenuHandler menuHandler;

    @Autowired
    private MsgHandler msgHandler;

    @Autowired
    private UnsubscribeHandler unsubscribeHandler;

    @Autowired
    private SubscribeHandler subscribeHandler;

    private WxMpMessageRouter router;

    @Autowired
    private ScanHandler scanHandler;

    @Autowired
    private MpUserMapper mpUserMapper;

    @Override
    public WxMpXmlOutMessage handleMsg(WxMpXmlMessage msg) {
        return route(msg);
    }

    @Override
    public WxMpService getWXServies() {
        return wxMpService;
    }

    @Override
    public WxMpQrCodeTicket generateQRCode(Integer doctorId) throws WxErrorException {
        return wxMpService.getQrcodeService().qrCodeCreateLastTicket(doctorId);
    }

    @Override
    public Boolean sendMpMsg(String unionId, String data) {
        MpUserExample ex = new MpUserExample();
        ex.createCriteria().andUnionidEqualTo(unionId);
        List<MpUser> res = mpUserMapper.selectByExample(ex);
        if(res.size()==0) {
            return false;
        }
        try {
            wxMpService.getTemplateMsgService().sendTemplateMsg(TemplateMsgHelper.MsgPushBuilder(data, res.get(0).getOpenid()));
        } catch (WxErrorException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public boolean sendMpMsgText(String unionid, String msgContent) {
        MpUserExample ex = new MpUserExample();
        ex.createCriteria().andUnionidEqualTo(unionid);
        List<MpUser> res = mpUserMapper.selectByExample(ex);
        if(res.size()==0) {
            return false;
        }
        try {
            wxMpService.getTemplateMsgService().sendTemplateMsg(TemplateMsgHelper.TempTextMsgBuilder(res.get(0).getOpenid(), msgContent));
        } catch (WxErrorException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        final WxMpInMemoryConfigStorage config = new WxMpInMemoryConfigStorage();
        config.setAppId(WxMpConfig.getAppid());// 设置微信公众号的appid
        config.setSecret(WxMpConfig.getSecret());// 设置微信公众号的app corpSecret
        config.setToken(WxMpConfig.getToken());// 设置微信公众号的token
        config.setAesKey(WxMpConfig.getAesKey());// 设置消息加解密密钥
        //避免http连接超时导致的 api.weixin.com no respond错误，tomcat默认的超时时间是20s
        DefaultApacheHttpClientBuilder clientBuilder = DefaultApacheHttpClientBuilder.get();
        clientBuilder.setIdleConnTimeout(20*1000);//空闲链接的超时时间(单位ms)
        clientBuilder.setCheckWaitTime(19*1000);//空闲链接的检测周期(单位ms)
        config.setApacheHttpClientBuilder(clientBuilder);
        wxMpService.setWxMpConfigStorage(config);
        this.refreshRouter();
    }
    private void refreshRouter() {
        final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);

        // 记录所有事件的日志
        newRouter.rule().handler(this.logHandler).next();

        // 接收客服会话管理事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxMpEventConstants.CustomerService.KF_CREATE_SESSION)
                .handler(this.kfSessionHandler).end();
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxMpEventConstants.CustomerService.KF_CLOSE_SESSION)
                .handler(this.kfSessionHandler).end();
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxMpEventConstants.CustomerService.KF_SWITCH_SESSION)
                .handler(this.kfSessionHandler).end();

        // 门店审核事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxMpEventConstants.POI_CHECK_NOTIFY)
                .handler(this.storeCheckNotifyHandler)
                .end();

        // 自定义菜单事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.MenuButtonType.CLICK).handler(this.getMenuHandler()).end();

        // 点击菜单连接事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.MenuButtonType.VIEW).handler(this.nullHandler).end();

        // 关注事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.SUBSCRIBE).handler(this.getSubscribeHandler())
                .end();

        // 取消关注事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.UNSUBSCRIBE).handler(this.getUnsubscribeHandler())
                .end();

        // 上报地理位置事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.LOCATION).handler(this.getLocationHandler()).end();

        // 接收地理位置消息
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION)
                .handler(this.getLocationHandler()).end();

        // 扫码事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.SCAN).handler(this.getScanHandler()).end();

        // 默认
        newRouter.rule().async(false).handler(this.getMsgHandler()).end();

        this.router = newRouter;
    }


    public WxMpXmlOutMessage route(WxMpXmlMessage message) {
        try {
            return this.router.route(message);
        } catch (Exception e) {
            this.logger.error(e.getMessage(), e);
        }

        return null;
    }

    protected MenuHandler getMenuHandler() {
        return this.menuHandler;
    }

    protected SubscribeHandler getSubscribeHandler() {
        return this.subscribeHandler;
    }

    protected UnsubscribeHandler getUnsubscribeHandler() {
        return this.unsubscribeHandler;
    }

    protected AbstractHandler getLocationHandler() {
        return this.locationHandler;
    }

    protected MsgHandler getMsgHandler() {
        return this.msgHandler;
    }

    protected AbstractHandler getScanHandler() {
        return this.scanHandler;
    }
}
